home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / misc / FetchRefs1.3.lha / FetchRefs1.3 / Source.lha / Source / GenerateIndex / Lists.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-02  |  23.8 KB  |  1,162 lines

  1. #include "GenerateIndex.h"
  2.  
  3. APTR FilePool;
  4. BOOL KeepScanning;
  5.  
  6. struct Prefs Settings;
  7. UBYTE DataName[256];
  8.  
  9. /// Timing functions. Useful when doing benchmarks.
  10. struct DateStamp StartTime, StopTime;
  11.  
  12. void
  13. StartTimer(void)
  14. {
  15.     DateStamp(&StartTime);
  16. }
  17.  
  18. void
  19. StopTimer(void)
  20. {
  21.     ULONG diff;
  22.  
  23.     DateStamp(&StopTime);
  24.     diff = ((StopTime.ds_Days   - StartTime.ds_Days) * 24 * 60 * 60 * 50)
  25.      + ((StopTime.ds_Minute - StartTime.ds_Minute)         * 60 * 50)
  26.      + ( StopTime.ds_Tick   - StartTime.ds_Tick                     );
  27.     Printf("Timer was on for %ld ticks = %ld.%02ld seconds\n", diff, diff / 50, (diff % 50) * 2);
  28. }
  29. ///
  30.  
  31. /// LoadData() - ask for and load a data file
  32. void
  33. LoadData(STRPTR name)
  34. {
  35.     STRPTR filename;
  36.     struct Node node;
  37.     FILE *file;
  38.     struct List *currentfile;
  39.  
  40.     filename = name;
  41.     
  42.     if (!name)
  43.     {
  44.     if (rtFileRequest(DataFileReq, DataName,
  45.               "Load file...",
  46.  
  47.               TAG_END))
  48.         filename = JoinPath(DataFileReq->Dir, DataName);
  49.  
  50.     if (!filename)
  51.         return;
  52.     }
  53.     
  54.     DetachMainList();
  55.  
  56.     if (file = fopen(filename, "r"))
  57.     {
  58.     while (fread(&node, sizeof(struct Node), 1, file) > 0)
  59.     {
  60.         if (node.ln_Type == 1)
  61.         {
  62.         struct FileEntry *entry;
  63.  
  64.         if (entry = LibAllocPooled(FilePool, (LONG)node.ln_Succ))
  65.         {
  66.             entry->node.ln_Type = node.ln_Type;
  67.             entry->node.ln_Name = entry->Name;
  68.             fread(entry->afternode, ((LONG)node.ln_Succ) - sizeof(struct Node), 1, file);
  69.             NewList(currentfile = &entry->RefsList);
  70.  
  71.             AddTail(&FileList, &entry->node);
  72.         } else
  73.             fseek(file, ((LONG)node.ln_Succ) - sizeof(struct Node), SEEK_CUR);
  74.         } else if (node.ln_Type == 2)
  75.         {
  76.         struct RefsEntry *entry;
  77.  
  78.         if (entry = LibAllocPooled(FilePool, (LONG)node.ln_Succ))
  79.         {
  80.             entry->node.ln_Type = node.ln_Type;
  81.             entry->node.ln_Name = entry->Name;
  82.             fread(entry->afternode, ((LONG)node.ln_Succ) - sizeof(struct Node), 1, file);
  83.  
  84.             AddTail(currentfile, &entry->node);
  85.         } else
  86.             fseek(file, ((LONG)node.ln_Succ) - sizeof(struct Node), SEEK_CUR);
  87.         }
  88.     }
  89.     fclose(file);
  90.     }
  91.  
  92.     AttachMainList(NULL);
  93.  
  94.     if (!name)
  95.     FreeVec(filename);
  96. }
  97. ///
  98. /// SaveData() - ask for filename and save data to a file
  99. void
  100. SaveData(STRPTR name)
  101. {
  102.     STRPTR filename;
  103.     struct FileEntry *entry;
  104.     struct RefsEntry *refentry;
  105.     FILE *file;
  106.     void *copy;
  107.  
  108.     filename = name;
  109.     
  110.     if (!name)
  111.     {
  112.     if (rtFileRequest(DataFileReq, DataName,
  113.               "Save as...",
  114.  
  115.               RTFI_Flags,    FREQF_SAVE,
  116.               TAG_END))
  117.         filename = JoinPath(DataFileReq->Dir, DataName);
  118.  
  119.     if (!filename)
  120.         return;
  121.     }
  122.  
  123.     entry = (struct FileEntry *)GetHead(&FileList);
  124.  
  125.     if (file = fopen(filename, "w"))
  126.     {
  127.     void *buf;
  128.  
  129.     FileChanged = FALSE;
  130.  
  131.     /* Bigger buffer gives faster I/O */
  132.     if (buf = AllocVec(16 * 1024, NULL))
  133.         setvbuf(file, buf, _IOFBF, 16 * 1024);
  134.  
  135.     while (entry->node.ln_Succ)
  136.     {
  137.         int size;
  138.  
  139.         copy = entry->node.ln_Succ;
  140.         size = ((sizeof(struct FileEntry) + strlen(entry->node.ln_Name) + 1) + 1) & ~1;
  141.         entry->node.ln_Succ = (void *)size;
  142.         fwrite(entry, 1, size, file);
  143.         entry->node.ln_Succ = copy;
  144.  
  145.         refentry = GetHead(&entry->RefsList);
  146.         while (refentry->node.ln_Succ)
  147.         {
  148.         copy = refentry->node.ln_Succ;
  149.         size = ((sizeof(struct RefsEntry) + strlen(refentry->node.ln_Name) + 1) + 1) & ~1;
  150.         refentry->node.ln_Succ = (void *)size;
  151.         fwrite(refentry, 1, size, file);
  152.         refentry->node.ln_Succ = copy;
  153.  
  154.         refentry = refentry->node.ln_Succ;
  155.         }
  156.  
  157.         entry = entry->node.ln_Succ;
  158.     }
  159.     fclose(file);
  160.     FreeVec(buf);
  161.     }
  162.  
  163.     if (!name)
  164.     FreeVec(filename);
  165. }
  166. ///
  167.  
  168. /// IndexFileList() - call IndexFile() for each file from a ReqTools filereq
  169. void
  170. IndexFileList(STRPTR path, struct rtFileList *lst)
  171. {
  172.     STRPTR dir;
  173.  
  174.     if (!(dir = FullName(path)))
  175.     return;
  176.  
  177.     do
  178.     {
  179.     if (lst->StrLen == -1)
  180.         IndexRecursive(dir, lst->Name);
  181.     else
  182.         IndexFile(dir, lst->Name);
  183.     } while ((lst = lst->Next) && (KeepScanning));
  184.     FreeVec(dir);
  185. }
  186. ///
  187. /// IndexRecursive() - call IndexFile() for files and itself for dirs
  188. void
  189. IndexRecursive(STRPTR path, STRPTR dir)
  190. {
  191.     BPTR lock;
  192.     STRPTR name;
  193.     struct FileInfoBlock *fib;
  194.  
  195.     if (!KeepScanning)
  196.     return;
  197.  
  198.     fib = AllocDosObject(DOS_FIB, NULL);
  199.     name = JoinPath(path, dir);
  200.     lock = Lock(name, ACCESS_READ);
  201.  
  202.     if (fib && name && lock)
  203.     {
  204.     Examine(lock, fib);
  205.     while (ExNext(lock, fib))
  206.     {
  207.         if (fib->fib_DirEntryType < 0)
  208.         IndexFile(name, fib->fib_FileName);
  209.         else if (Settings.Recursively)
  210.         IndexRecursive(name, fib->fib_FileName);
  211.     }
  212.     }
  213.  
  214.     UnLock(lock);
  215.     FreeVec(name);
  216.     if (fib)
  217.     FreeDosObject(DOS_FIB, fib);
  218. }
  219. ///
  220. /// IndexFile() - index a file, taking care of all settings, and add to list
  221. void
  222. IndexFile(STRPTR dir, STRPTR filename)
  223. {
  224.     BPTR lock;
  225.     STRPTR name, buf, end;
  226.  
  227.     if (!KeepScanning)
  228.     return;
  229.  
  230.     /* Join path and name unless they already are joined */
  231.     if (!dir)
  232.     name = filename;
  233.     else if (!(name = JoinPath(dir, filename)))
  234.     return;
  235.  
  236.     if (lock = Lock(name, SHARED_LOCK))
  237.     {
  238.     LONG bufsize;
  239.     BPTR file;
  240.  
  241.     bufsize = FileLength(lock);
  242.  
  243.     if (!(file = OpenFromLock(lock)))
  244.         UnLock(lock);
  245.     else if (buf = AllocVec(bufsize + 1, NULL))
  246.     {
  247.         /* We add one extra byte to make sure that the file is '\0'
  248.          * terminated. Some of the scanning routines depend on this.
  249.          */
  250.  
  251.         LONG filetype;
  252.  
  253.         Read(file, buf, bufsize);
  254.         Close(file);
  255.         end = buf + bufsize;
  256.         *end = 0;
  257.  
  258.         filetype = FileType(buf, bufsize);
  259.         if (filetype != FILE_UNKNOWN)
  260.         {
  261.         struct FileEntry *list;
  262.  
  263.         /* Remove the refs of the old one if a copy already exists.
  264.          * Otherwise allocate a new, empty list.
  265.          */
  266.         if (list = IsFileInList(lock, FilePart(name)))
  267.         {
  268.             struct Node *r;
  269.  
  270.             DetachRefList();
  271.             while (r = RemHead(&list->RefsList))
  272.             LibFreePooled(FilePool, r, sizeof(struct RefsEntry) + strlen(r->ln_Name) + 1);
  273.             AttachRefList();
  274.         } else
  275.             list = AddFileToList(name);
  276.  
  277.         if (list)
  278.         {
  279.             BOOL freefile = FALSE;
  280.  
  281.             switch (filetype)
  282.             {
  283.             case FILE_AUTODOC:
  284.                 ADocToList(list, buf, end);
  285.             break;
  286.  
  287.             case FILE_C:
  288.                 CToList(list, buf, end);
  289.             break;
  290.  
  291.             case FILE_E:
  292.                 EToList(list, buf, end);
  293.             break;
  294.  
  295.             case FILE_ASM:
  296.                 AsmToList(list, buf, end);
  297.             break;
  298.  
  299.             /* Warn user about wrong file type */
  300.             case FILE_EMODULE:
  301.             {
  302.                 static LONG warned;
  303.  
  304.                 if (!warned)
  305.                 PostMessage("You CANNOT scan E modules!\n"
  306.                         "Use the output of ShowModule instead."
  307.                        );
  308.  
  309.                 warned = TRUE;
  310.                 freefile = TRUE;
  311.             }
  312.             break;
  313.  
  314.             case FILE_AMIGAGUIDE:
  315.             {
  316.                 static LONG warned;
  317.  
  318.                 if (!warned)
  319.                 PostMessage("You CANNOT scan AmigaGuides! Use regular AutoDocs instead.\n"
  320.                         "You may use the Shell utility 'Guide2AutoDoc' from the\n"
  321.                         "FetchRefs archive (not installed by the Installer script)."
  322.                        );
  323.  
  324.                 warned = TRUE;
  325.                 freefile = TRUE;
  326.             }
  327.             break;
  328.             }
  329.  
  330.             if ((freefile) || ((!Settings.KeepEmpty) && IsListEmpty(&list->RefsList)))
  331.             FreeFile(list);
  332.             else
  333.             {
  334.             /* Sort the references of this file */
  335.             SortExecList(&((struct FileEntry *)GetTail(&FileList))->RefsList, SortCompareFunc, NULL);
  336.             FileChanged = TRUE;
  337.             }
  338.         }
  339.         }
  340.         FreeVec(buf);
  341.     }
  342.     }
  343.  
  344.     /* Only free if we actually joined names */
  345.     if (name != filename)
  346.     FreeVec(name);
  347.  
  348.     /* Check for IDCMP; user may have pressed 'Stop' */
  349.     HandleGUI();
  350. }
  351. ///
  352.  
  353. /// StartScanning() - initialize scanner
  354. void
  355. StartScanning(void)
  356. {
  357.     KeepScanning = TRUE;
  358.  
  359.     /* Make sure that the list view is empty as we are going to manipulate
  360.      * the list heavily (which GadTools does not allow when it is attached
  361.      * to a view).
  362.      */
  363.     AttachMainList(&EmptyList);
  364.  
  365.     OpenScanStatWindow();
  366. }
  367. ///
  368. /// StopScanning() - signal scanner that it is time to stop
  369. void
  370. StopScanning(BOOL force)
  371. {
  372.     KeepScanning = FALSE;
  373.     CloseScanStatWindow();
  374.  
  375.     if (!force)
  376.     AttachMainList(&FileList);
  377. }
  378. ///
  379.  
  380. /// FileType() - figure out what kind of file the buffer comes from
  381. LONG FileType(STRPTR buf, LONG bufsize)
  382. {
  383.     STRPTR b;
  384.     LONG checksize;
  385.  
  386.     for (checksize = 256; bufsize > 0; )
  387.     {
  388.     if (Settings.AutoDocPrf.Active)
  389.         if (FindKeyword(buf, "TABLE OF CONTENTS", checksize))
  390.         return FILE_AUTODOC;
  391.  
  392.     if (Settings.CPrf.Active)
  393.         if (FindKeyword(buf, "#if", checksize) || FindKeyword(buf, "#define", checksize))
  394.         return FILE_C;
  395.  
  396.     if (Settings.EPrf.Active)
  397.         if (FindKeyword(buf, "\n(---) OBJECT", checksize) ||
  398.         FindKeyword(buf, "\nCONST", checksize)        ||
  399.         FindKeyword(buf, "\nPROC", checksize)
  400.            )
  401.         return FILE_E;
  402.  
  403.     if (Settings.AsmPrf.Active)
  404.         if (FindKeyword(buf, "IFND", checksize)         ||
  405.         FindKeyword(buf, "EQU", checksize)          ||
  406.         FindKeyword(buf, "STRUCTURE", checksize)    ||
  407.         FindKeyword(buf, "MACRO", checksize)        ||
  408.         FindKeyword(buf, "BITDEF", checksize)
  409.            )
  410.         return FILE_ASM;
  411.  
  412.     /* Nothing found; adjust parameters */
  413.     buf = buf + (checksize - 10);
  414.     bufsize = bufsize - (checksize - 10);
  415.     checksize *= 2;
  416.     }
  417.  
  418.     /* A few unsupported file types to be able to warn the user */
  419.     if (0 == strncmp(buf, "EMOD", 4))
  420.     return FILE_EMODULE;
  421.  
  422.     if ((b = FindKeyword(buf, "@", bufsize)) && (0 == strnicmp(&b[1], "database", 8)))
  423.     return FILE_AMIGAGUIDE;
  424.  
  425.     /* Unrecognized file type - treat it as an AutoDoc? */
  426.     if (Settings.UnknownAsAutoDoc)
  427.     return FILE_AUTODOC;
  428.  
  429.     /* Everything failed. We really do not know this file type! */
  430.     return FILE_UNKNOWN;
  431. }
  432. ///
  433. /// FileLength() - returns file length of locked file
  434. LONG
  435. FileLength(BPTR lock)
  436. {
  437.     __aligned struct FileInfoBlock fib;
  438.  
  439.     Examine(lock, &fib);
  440.     return fib.fib_Size;
  441. }
  442. ///
  443. /// FindKeyword() - like strstr() but with length limit
  444. STRPTR
  445. FindKeyword(STRPTR buf, STRPTR keyword, LONG size)
  446. {
  447.     STRPTR c1, c2;
  448.  
  449.     do
  450.     {
  451.     c1 = buf;
  452.     c2 = keyword;
  453.  
  454.     while ((*c1) && (*c1 == *c2))
  455.         c1++, c2++;
  456.  
  457.     if (!*c2)
  458.         return buf;
  459.  
  460.     } while((*buf++) && (size--));
  461.  
  462.     return NULL;
  463. }
  464. ///
  465.  
  466. /// FullName() - return pointer to AllocVec()'ed full path of arg
  467. STRPTR
  468. FullName(STRPTR path)
  469. {
  470.     UBYTE *dir;
  471.  
  472.     dir = path;
  473.     while (*dir)
  474.     if (*dir++ == ':')
  475.     {
  476.         if (dir = AllocVec(strlen(path) + 1, NULL))
  477.         strcpy(dir, path);
  478.         return(dir);
  479.     }
  480.  
  481.     if (dir = AllocVec(512, NULL))
  482.     {
  483.     BPTR lok;
  484.  
  485.     if (lok = Lock(path, ACCESS_READ))
  486.     {
  487.         NameFromLock(lok, dir, 512);
  488.         UnLock(lok);
  489.     }
  490.     }
  491.     return(dir);
  492. }
  493. ///
  494. /// JoinPath() - return ptr to AllocVec()'ed joined file name
  495. UBYTE *
  496. JoinPath(STRPTR dir, STRPTR name)
  497. {
  498.     LONG len;
  499.     UBYTE *both;
  500.  
  501.     len = strlen(dir) + 1 + strlen(name) + 1;
  502.  
  503.     if (both = AllocVec(len, NULL))
  504.     {
  505.     strcpy(both, dir);
  506.     if (name[0])
  507.         AddPart(both, name, len);
  508.     }
  509.     return(both);
  510. }
  511. ///
  512.  
  513. /// ADocToList() - add the references of an AutoDoc to the list
  514. void
  515. ADocToList(struct FileEntry *list, STRPTR buf, STRPTR end)
  516. {
  517.     STRPTR at, ff;
  518.  
  519.     at = ff = buf;
  520.  
  521.     /* Scan entire file */
  522.     while (at < end)
  523.     {
  524.     STRPTR left, right;
  525.     LONG rightlen = 0;
  526.  
  527.     /* Find next reference end (at a form feed) */
  528.     if (at >= ff)
  529.     {
  530.         /* Stop at next form feed or at the end of the file */
  531.         do
  532.         ff++;
  533.         while ((ff < end) && (*ff != 12));
  534.     }
  535.  
  536.     /* Find the start and end of the next line with text */
  537.     for (left = at; (*left == '\f') || (*left == '\n') || (*left == ' ') || (*left == '\t'); )
  538.         left++;
  539.     for (right = left; (*right != '\n') && (*right != '\f') && (right < end); )
  540.         right++;
  541.     at = right + 1;
  542.  
  543.     /* Set 'right' to point to the start of the last word of the
  544.      * line. After this 'left' will point to the first word and
  545.      * 'right' to the last one.
  546.      */
  547.     *right = 0;
  548.     while ((right[-1] == ' ') || (right[-1] == '\t'))
  549.         *right-- = 0;
  550.     while ((right[-1] != ' ') && (right[-1] != '\t'))
  551.         right--, rightlen++;
  552.  
  553.     /* Make sure that we actually have >1 words on this line.
  554.      * If we do, then check if the first and the last words are
  555.      * alike; that is the format of a new AutoDoc entry.
  556.      */
  557.     if ((right > left) && (0 == strncmp(left, right, rightlen)))
  558.     {
  559.         /* Set 'right' to point to the start of the name.
  560.          * This is so 'exec.library/AllocVec' will only
  561.          * be remembered as 'AllocVec'. Quite important.
  562.          */
  563.         right += rightlen;
  564.         while (IsAlphaNum(right[-1]))
  565.            right--;
  566.  
  567.         AddRefToList(list, left - buf, ff - left, 0, right);
  568.     } else /* No more head lines, jump to next entry */
  569.         at = ff;
  570.     }
  571. }
  572. ///
  573. /// CToList() - add the references of a C include file to the list
  574. void
  575. CToList(struct FileEntry *list, STRPTR buf, STRPTR end)
  576. {
  577.     STRPTR at;
  578.     UBYTE name[128];
  579.  
  580.     /* Remove all comments */
  581.     at = buf;
  582.     while (at < end)
  583.     {
  584.     if ((at[0] == '/') && (at[1] == '*'))
  585.     {
  586.         *at++ = ' ';
  587.         do
  588.         {
  589.         if (*at != '\n')
  590.             *at = ' ';
  591.         at++;
  592.  
  593.         if (at + 2 == end)
  594.             break;
  595.         } while ((at[0] != '*') || (at[1] != '/'));
  596.         *at++ = ' ';
  597.         *at++ = ' ';
  598.     } else if ((at[0] == '/') && (at[1] == '/'))
  599.     {
  600.         do
  601.         *at++ = ' ';
  602.         while ((*at != '\n') && (at < end));
  603.     } else
  604.         at++;
  605.     }
  606.  
  607.     if (Settings.CPrf.Define)
  608.     {
  609.     LONG line = 1;
  610.  
  611.     at = buf;
  612.     while (at < end)
  613.     {
  614.  
  615.         if (*at == '\n')
  616.         line++;
  617.         else if ( (at[0] == '#') && (at[1] == 'd') && (at[2] == 'e') && (at[3] == 'f')
  618.             && (at[4] == 'i') && (at[5] == 'n') && (at[6] == 'e') )
  619.         {
  620.         at = PickName(name, at + 7) - 1;
  621.         AddRefToList(list, 0, -1, line, name);
  622.         }
  623.  
  624.         at++;
  625.     }
  626.     }
  627.  
  628.     if (Settings.CPrf.Struct)
  629.     {
  630.     STRPTR lastend = buf;
  631.     LONG line = 1;
  632.  
  633.     at = FindStructUnion(buf, end, &line);
  634.  
  635.     while (at)
  636.     {
  637.         STRPTR start;
  638.         LONG len, jump, level;
  639.  
  640.         /* Get the name of this struct/union */
  641.         at = PickName(name, at + 6);
  642.  
  643.         /* Find end of struct/union */
  644.         while (*at++ != '{')
  645.         ;
  646.         for (level = 1; level; at++)
  647.         {
  648.         if (*at == '{')
  649.             level++;
  650.         else if (*at == '}')
  651.             level--;
  652.         }
  653.         while (*at++ != ';')
  654.         ;
  655.  
  656.         start = lastend;
  657.         jump = line;
  658.         lastend = at;
  659.         line = 1;
  660.  
  661.         /* Find start of the _next_ struct/union. This is
  662.          * also the end of this reference.
  663.          */
  664.         at = FindStructUnion(at, end, &line);
  665.         len = (at ? at : end) - start;
  666.  
  667.         AddRefToList(list, start - buf, len, jump, name);
  668.     }
  669.     }
  670.  
  671.     if (Settings.CPrf.Typedef)
  672.     {
  673.     LONG line = 1;
  674.  
  675.     at = buf;
  676.     while (at < end)
  677.     {
  678.         if (*at == '\n')
  679.         line++;
  680.         else if ( (at[0] == 't') && (at[1] == 'y') && (at[2] == 'p') && (at[3] == 'e')
  681.             && (at[4] == 'd') && (at[5] == 'e') && (at[6] == 'f') )
  682.         {
  683.         while ((*at != ';') && (at < end))
  684.             at++;
  685.         at--;
  686.  
  687.         while (IsAlphaNum(*at))
  688.             at--;
  689.         at++;
  690.  
  691.         at = PickName(name, at) - 1;
  692.         AddRefToList(list, 0, -1, line, name);
  693.         }
  694.  
  695.         at++;
  696.     }
  697.     }
  698. }
  699. ///
  700. /// EToList() - add the references of an E include file to the list
  701. void
  702. EToList(struct FileEntry *list, STRPTR buf, STRPTR end)
  703. {
  704.     STRPTR at;
  705.     UBYTE name[128];
  706.     LONG line;
  707.  
  708.     if (Settings.EPrf.Const)
  709.     {
  710.     line = 1;
  711.     at = buf;
  712.  
  713.     while (at < end)
  714.     {
  715.         if (*at == '\n')
  716.         {
  717.         line++;
  718.  
  719.         if ( (at[1] == 'C') && (at[2] == 'O') && (at[3] == 'N')
  720.             && (at[4] == 'S') && (at[5] == 'T') )
  721.         {
  722.             STRPTR start = at + 1, stop;
  723.             LONG lines;
  724.  
  725.             /* Find end of CONST block */
  726.             for (stop = at + 1; ; stop++)
  727.             if ((*stop == '\n') && (strncmp(&stop[1], "     ", 5)))
  728.                 break;
  729.             stop--;
  730.  
  731.             /* Add each CONST entry */
  732.             for (lines = 1; at < stop; lines++)
  733.             {
  734.             at = PickName(name, at + 7);
  735.             AddRefToList(list, start - buf, stop - start, lines, name);
  736.  
  737.             while ((*at) && (*at != '\n'))
  738.                 at++;
  739.             }
  740.         }
  741.         }
  742.  
  743.         at++;
  744.     }
  745.     }
  746.  
  747.     if (Settings.EPrf.Object)
  748.     {
  749.     line = 1;
  750.     at = buf;
  751.  
  752.     while (at < end)
  753.     {
  754.         if (*at == '\n')
  755.         line++;
  756.         else if ( (at[0] == 'O') && (at[1] == 'B') && (at[2] == 'J')
  757.             && (at[3] == 'E') && (at[4] == 'C') && (at[5] == 'T') )
  758.         {
  759.         STRPTR stop;
  760.         LONG len;
  761.  
  762.         /* Find end of OBJECT block */
  763.         if (stop = strstr(at, "ENDOBJECT"))
  764.         {
  765.             while ((*stop) && (*stop != '\n'))
  766.             stop++;
  767.  
  768.             len = stop - at;
  769.             stop--;
  770.  
  771.             /* Save reference */
  772.             PickName(name, at + 6);
  773.             AddRefToList(list, at - buf, len, 0, name);
  774.             at = stop;
  775.         }
  776.         }
  777.  
  778.         at++;
  779.     }
  780.     }
  781.  
  782.     if (Settings.EPrf.Proc)
  783.     {
  784.     line = 1;
  785.  
  786.     for (at = buf; at < end; at++)
  787.         if (*at == '\n')
  788.         {
  789.         line++;
  790.  
  791.         if ( (at[1] == 'P') && (at[2] == 'R') && (at[3] == 'O')
  792.             && (at[4] == 'C') )
  793.         {
  794.             STRPTR c;
  795.  
  796.             at++;
  797.             for (c = at; (*c) && (*c != '\n'); c++)
  798.             ;
  799.  
  800.             PickName(name, at + 5);
  801.             AddRefToList(list, at - buf, c - at, 0, name);
  802.             at = c;
  803.         }
  804.         }
  805.     }
  806. }
  807. ///
  808. /// AsmToList() - add the references of an Asm include file to the list
  809. void
  810. AsmToList(struct FileEntry *list, STRPTR buf, STRPTR end)
  811. {
  812.     STRPTR at;
  813.     UBYTE name[128];
  814.     LONG line;
  815.  
  816.     /* Remove comments */
  817.     for (at = buf; at < end; at++)
  818.     if ((*at == ';') || (*at == '*'))
  819.         while ((*at) && (*at != '\n'))
  820.         *at++ = ' ';
  821.  
  822.     if (Settings.AsmPrf.Equ)
  823.     {
  824.     line = 1;
  825.     at = buf;
  826.  
  827.     while (at < end)
  828.     {
  829.         /* Handle EQU definiton */
  830.         if ( ((at[1]|0x20) == 'e') && ((at[2]|0x20) == 'q') && ((at[3]|0x20) == 'u')
  831.         && (at[0] == ' ' || at[0] == '\t')
  832.         && (at[4] == ' ' || at[4] == '\t') )
  833.         {
  834.         /* Find word before EQU */
  835.         while (*at == ' ' || *at == '\t')
  836.             at--;
  837.         while (IsAlphaNum(*at))
  838.             at--;
  839.  
  840.         /* If the word starts with a backslash (92) it is probably
  841.          * part of a macro and we ignore it.
  842.          */
  843.         if (*at != 92)
  844.         {
  845.             at++;
  846.             PickName(name, at);
  847.             AddRefToList(list, 0, -1, line, name);
  848.         }
  849.  
  850.         while ((*at) && (*at != '\n'))
  851.             at++;
  852.         }
  853.  
  854.         /* Unroll BITDEF macro */
  855.         if ( ((at[0]|0x20) == 'b') && ((at[1]|0x20) == 'i') && ((at[2]|0x20) == 't')
  856.         && ((at[3]|0x20) == 'd') && ((at[4]|0x20) == 'e') && ((at[5]|0x20) == 'f')
  857.         && (at[6] == ' ' || at[6] == '\t') )
  858.         {
  859.         UBYTE mprefix[32], mname[32];
  860.         ULONG i;
  861.  
  862.         at += 6;
  863.         while (*at == ' ' || *at == '\t')
  864.             at++;
  865.  
  866.         for (i = 0; IsAlphaNum(*at); )
  867.             mprefix[i++] = *at++;
  868.         mprefix[i] = 0;
  869.  
  870.         if (*at == ',')
  871.         {
  872.             while (!IsAlphaNum(*at))
  873.             at++;
  874.  
  875.             for (i = 0; IsAlphaNum(*at); )
  876.             mname[i++] = *at++;
  877.             mname[i] = 0;
  878.  
  879.             /* Build e.g. MEMB_CLEAR */
  880.             strcpy(name, mprefix);
  881.             strcat(name, "B_");
  882.             strcat(name, mname);
  883.             AddRefToList(list, 0, -1, line, name);
  884.             
  885.             /*  Change to MEMF_CLEAR */
  886.             name[strlen(mprefix)] = 'F';
  887.             AddRefToList(list, 0, -1, line, name);
  888.         }
  889.  
  890.         while ((*at) && (*at != '\n'))
  891.             at++;
  892.         }
  893.  
  894.         if (*at == '\n')
  895.         line++;
  896.         at++;
  897.     }
  898.     }
  899.  
  900.     if (Settings.AsmPrf.Structure)
  901.     {
  902.     line = 1;
  903.     at = buf;
  904.  
  905.     while (at < end)
  906.     {
  907.         if ( ((at[0]|0x20) == 's') && ((at[1]|0x20) == 't') && ((at[2]|0x20) == 'r')
  908.         && ((at[3]|0x20) == 'u') && ((at[4]|0x20) == 'c') && ((at[5]|0x20) == 't')
  909.         && ((at[6]|0x20) == 'u') && ((at[7]|0x20) == 'r') && ((at[8]|0x20) == 'e')
  910.         && (at[9] == ' ' || at[9] == '\t') )
  911.         {
  912.         at = PickName(name, at + 9);
  913.         while ((*at) && (*at != '\n'))
  914.             at++;
  915.  
  916.         /* Workaround for the 'STRUCTURE MACRO' definition */
  917.         if (stricmp(name, "MACRO"))
  918.             AddRefToList(list, 0, -1, line, name);
  919.         }
  920.  
  921.         if (*at == '\n')
  922.         line++;
  923.         at++;
  924.     }
  925.     }
  926.  
  927.     if (Settings.AsmPrf.Macro)
  928.     {
  929.     line = 1;
  930.     at = buf;
  931.  
  932.     while (at < end)
  933.     {
  934.         if ( ((at[0]|0x20) == 'm') && ((at[1]|0x20) == 'a') && ((at[2]|0x20) == 'c')
  935.         && ((at[3]|0x20) == 'r') && ((at[4]|0x20) == 'o')
  936.         && (at[5] == ' ' || at[5] == '\t' || at[5] == '\n') )
  937.         {
  938.         /* Find name before MACRO */
  939.         at--;
  940.         while (*at == ' ' || *at == '\t')
  941.             at--;
  942.  
  943.         /* A few macros, like PARALLELNAME, have a colon here */
  944.         if (*at == ':')
  945.             at--;
  946.  
  947.         while (IsAlphaNum(*at))
  948.             at--;
  949.         at++;
  950.         
  951.         at = PickName(name, at);
  952.         while ((*at) && (*at != '\n'))
  953.             at++;
  954.  
  955.         AddRefToList(list, 0, -1, line, name);
  956.         }
  957.  
  958.         if (*at == '\n')
  959.         line++;
  960.         at++;
  961.     }
  962.     }
  963. }
  964. ///
  965.  
  966. /// FindStructUnion() - return pointer to start of next struct/union definition
  967. STRPTR
  968. FindStructUnion(STRPTR ptr, STRPTR end, LONG *l)
  969. {
  970.     STRPTR ret;
  971.     UBYTE name[128];
  972.  
  973.     while (ptr <= end)
  974.     {
  975.     if (*ptr == '\n')
  976.         *l = *l + 1;
  977.     else if ( ((ptr[0] == 's') && (ptr[1] == 't') && (ptr[2] == 'r') && (ptr[3] == 'u') && (ptr[4] == 'c') && (ptr[5] == 't'))
  978.      || ((ptr[0] == 'u') && (ptr[1] == 'n') && (ptr[2] == 'i') && (ptr[3] == 'o') && (ptr[4] == 'n')) )
  979.     {
  980.         /* Pick next word */
  981.         ret = ptr;
  982.         ptr = PickName(name, ptr + 6);
  983.  
  984.         if (name[0])
  985.         {
  986.         /* Find '{' (hopefully) */
  987.         while (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\f')
  988.             ptr++;
  989.  
  990.         /* If the format is 'struct <name> {' we have one */
  991.         if (*ptr == '{')
  992.             return ret;
  993.         }
  994.     }
  995.  
  996.     ptr++;
  997.     }
  998.     return NULL;
  999. }
  1000. ///
  1001. /// PickName() - skip initial white space and return next word
  1002. STRPTR
  1003. PickName(STRPTR buf, STRPTR ptr)
  1004. {
  1005.     while (*ptr == ' ' || *ptr == '\t')
  1006.     ptr++;
  1007.     while (IsAlphaNum(*ptr))
  1008.     *buf++ = *ptr++;
  1009.     *buf = 0;
  1010.     return(ptr);
  1011. }
  1012. ///
  1013. /// IsAlphaNum() - returns whether a character is [A-Za-z0-9_]
  1014. BOOL
  1015. IsAlphaNum(UBYTE c)
  1016. {
  1017.     if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
  1018.     (c >= '0' && c <= '9') || (c == '_'))
  1019.     return TRUE;
  1020.  
  1021.     return FALSE;
  1022. }
  1023. ///
  1024. /// SortCompareFunc() - call back function for sortlist.lib functions
  1025. BOOL
  1026. SortCompareFunc(struct FileEntry *a, struct FileEntry *b, ULONG data)
  1027. {
  1028.     return( stricmp(a->node.ln_Name, b->node.ln_Name) > 0 );
  1029. }
  1030. ///
  1031.  
  1032. /// AddFileToList() - append arg to list of indexed files
  1033. struct FileEntry *
  1034. AddFileToList(STRPTR name)
  1035. {
  1036.     struct FileEntry *entry;
  1037.  
  1038.     if (entry = LibAllocPooled(FilePool, sizeof(struct FileEntry) + strlen(name) + 1))
  1039.     {
  1040.     strcpy(entry->Name, name);
  1041.     entry->node.ln_Name = entry->Name;
  1042.     entry->node.ln_Type = 1;
  1043.     NewList(&entry->RefsList);
  1044.  
  1045.     AddTail(&FileList, &entry->node);
  1046.     }
  1047.     return(entry);
  1048. }
  1049. ///
  1050. /// AddRefToList() - add a ref to the list of refs of the specified file
  1051. struct RefsEntry *
  1052. AddRefToList(struct FileEntry *fileentry, LONG offset, LONG length, WORD gotoline, STRPTR name)
  1053. {
  1054.     struct RefsEntry *entry;
  1055.  
  1056.     /* Do not add the reference if the name is empty (ie ""). */
  1057.     if (!name[0])
  1058.     return(NULL);
  1059.  
  1060.     if (entry = LibAllocPooled(FilePool, sizeof(struct RefsEntry) + strlen(name) + 1))
  1061.     {
  1062.     entry->Offset = offset;
  1063.     entry->Length = length;
  1064.     entry->Goto = gotoline;
  1065.     strcpy(entry->Name, name);
  1066.     entry->node.ln_Name = entry->Name;
  1067.     entry->node.ln_Type = 2;
  1068.  
  1069.     AddTail(&fileentry->RefsList, &entry->node);
  1070.     }
  1071.     return(entry);
  1072. }
  1073. ///
  1074. /// IsFileInList() - return ptr to FileEntry of lock
  1075. struct FileEntry *
  1076. IsFileInList(BPTR newlock, STRPTR filepart)
  1077. {
  1078.     struct Node *n;
  1079.  
  1080.     if (n = GetHead(&FileList))
  1081.     {
  1082.     for (; n->ln_Succ; n = n->ln_Succ)
  1083.     {
  1084.         /* Check if filenames are the same */
  1085.         if (0 == strcmp(FilePart(n->ln_Name), filepart))
  1086.         {
  1087.         BPTR oldlock;
  1088.  
  1089.         /* Check if this really is the same file */
  1090.         if (oldlock = Lock(n->ln_Name, SHARED_LOCK))
  1091.         {
  1092.             LONG val;
  1093.  
  1094.             val = SameLock(oldlock, newlock);
  1095.             UnLock(oldlock);
  1096.  
  1097.             if (val == LOCK_SAME)
  1098.             return ((struct FileEntry *)n);
  1099.         }
  1100.         }
  1101.     }
  1102.     }
  1103.  
  1104.     return NULL;
  1105. }
  1106. ///
  1107. /// FreeFile() - free a FileEntry and all references in it
  1108. void
  1109. FreeFile(struct FileEntry *f)
  1110. {
  1111.     struct Node *n;
  1112.  
  1113.     /* Free all references of the file */
  1114.     DetachRefList();
  1115.     while (n = RemHead(&f->RefsList))
  1116.     LibFreePooled(FilePool, n, sizeof(struct RefsEntry) + strlen(n->ln_Name) + 1);
  1117.     AttachRefList();
  1118.  
  1119.     /* Free the file itself */
  1120.     Remove(&f->node);
  1121.     LibFreePooled(FilePool, f, sizeof(struct FileEntry) + strlen(f->node.ln_Name) + 1);
  1122. }
  1123. ///
  1124. /// FreeRef() - free just a reference in a FileEntry
  1125. void
  1126. FreeRef(struct RefsEntry *r)
  1127. {
  1128.     /* Detach the reference and free the memory to the pool */
  1129.     DetachRefList();
  1130.     Remove(&r->node);
  1131.     AttachRefList();
  1132.     LibFreePooled(FilePool, r, sizeof(struct RefsEntry) + strlen(r->node.ln_Name) + 1);
  1133. }
  1134. ///
  1135. /// InitializeFileList() - prepare a memory pool and Exec list
  1136. void
  1137. InitializeFileList(void)
  1138. {
  1139.     if (FilePool)
  1140.     FreeFileList();
  1141.  
  1142.     DetachMainList();
  1143.     DetachRefList();
  1144.     NewList(&FileList);
  1145.     AttachMainList(NULL);
  1146.     AttachRefList();
  1147.  
  1148.     if (!(FilePool = LibCreatePool(NULL, 8192, 8192)))
  1149.     CloseAll(ERROR_NO_FREE_STORE);
  1150. }
  1151. ///
  1152. /// FreeFileList() - remove the memory pool of indexed files
  1153. void
  1154. FreeFileList(void)
  1155. {
  1156.     /* Free existing pool, just in case one exists */
  1157.     LibDeletePool(FilePool);
  1158.     FilePool = NULL;
  1159. }
  1160. ///
  1161.  
  1162.